#pragma once

#include <QObject>
#include <QAudioOutput>
#include <memory>
#include <vector>
#include "qgbcore.h"

class Speaker: public QObject
{
    Q_OBJECT

public:
    Speaker(QObject* parent = nullptr) : QObject(parent)
    {
        buffer.reserve(1024);

        QAudioFormat format;
        format.setSampleRate(44100);
        format.setChannelCount(2);
        format.setSampleSize(16);
        format.setCodec("audio/pcm");
        format.setByteOrder(QAudioFormat::LittleEndian);
        format.setSampleType(QAudioFormat::SignedInt);

        QAudioDeviceInfo dev = QAudioDeviceInfo::defaultOutputDevice();
        if (!dev.isFormatSupported(format)) {
            format = dev.nearestFormat(format);
        }

        m_audioOutput.reset(new QAudioOutput(dev, format));
        qreal linearVolume = QAudio::convertVolume(90 / qreal(100),
            QAudio::LogarithmicVolumeScale,
            QAudio::LinearVolumeScale);

        m_audioOutput->setVolume(linearVolume);
        qAudioDevice = m_audioOutput->start();
    }

    ~Speaker()
    {
        m_audioOutput.reset();
        qAudioDevice = nullptr;
    }

public slots:
    void update(qint16 left, qint16 right)
    {
        buffer.push_back(left);
        buffer.push_back(right);
    }

    void writeSound()
    {
        if (!buffer.empty()) {
            qAudioDevice->write((char*)&buffer[0], buffer.size() * 2);
            buffer.clear();
        }
    }

private:
	std::unique_ptr<QAudioOutput> m_audioOutput{ nullptr };
	QIODevice* qAudioDevice{ nullptr };
    std::vector<qint16> buffer;
};